package com.boot.project.admin.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.boot.project.admin.service.AuthService;
import com.boot.project.core.constant.SystemConstant;
import com.boot.project.core.enums.code.impl.commonCode.ResultCode;
import com.boot.project.core.enums.code.impl.systemCode.UserCode;
import com.boot.project.core.exception.CustomerException;
import com.boot.project.core.model.result.ProfileResult;
import com.boot.project.core.model.system.dto.UserLoginDto;
import com.boot.project.core.model.system.dto.UserPasswordDto;
import com.boot.project.core.model.system.entity.User;
import com.boot.project.admin.shiro.util.EncryptUtils;
import com.boot.project.core.util.RequestUtils;
import com.boot.project.module.system.mapper.UserMapper;
import com.wf.captcha.utils.CaptchaUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private UserMapper userMapper;

    /**
     * 用户登录
     * @param dto 登录信息
     */
    @Override
    public void login(UserLoginDto dto) {
        // 1.校验验证码
        HttpServletRequest request = RequestUtils.getRequest();
        if (!CaptchaUtil.ver(dto.getVerification(), request)) {
            // 清除session中的验证码
            CaptchaUtil.clear(request);
            throw new CustomerException(UserCode.INCORRECT_VERIFICATION);
        }
        // 2.获取Subject主体对象
        Subject subject = SecurityUtils.getSubject();

        // 3.封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(dto.getUsername(), dto.getPassword());

        // 4.执行登录，进入自定义Realm类中
        try {
            // 判断是否自动登录
            if (StrUtil.isNotBlank(dto.getRememberMe())) {
                token.setRememberMe(true);
            } else {
                token.setRememberMe(false);
            }
            subject.login(token);
        } catch (AuthenticationException e) {
            throw new CustomerException(UserCode.INCORRECT_USERNAME_OR_PASSWORD);
        } catch (Exception e) {
            throw new CustomerException(UserCode.INCORRECT_USERNAME_OR_PASSWORD, "登录时发生异常，请稍后再试");
        }
    }

    /**
     * 根据用户的标识查找对应的权限信息
     *
     * @return
     */
    @Override
    public ProfileResult profile() {
        // 以下是从Session中获取信息
        Subject subject = SecurityUtils.getSubject();
        // 获取所有的安全数据
        PrincipalCollection principals = subject.getPrincipals();
        // 获取并安全数据
        return (ProfileResult) principals.getPrimaryPrincipal();
    }

    /**
     * 管理员重置用户密码，将密码重置为初始密码
     *
     * @param userPasswordDto 操作需要的实体信息
     */
    @Override
    public void resetPassword(UserPasswordDto userPasswordDto) {
        if (ObjectUtil.isNull(userPasswordDto.getId())) {
            throw new CustomerException(ResultCode.HANDLE_DATA_NOT_EXISTED, "重置用户密码时，没有用户的id");
        }
        User dbUser = userMapper.selectById(userPasswordDto.getId());
        if (ObjectUtil.isNull(dbUser)) {
            throw new CustomerException(ResultCode.HANDLE_DATA_NOT_EXISTED, "重置用户密码时，没有用户的信息");
        }
        dbUser.setPassword(EncryptUtils.encrypt(SystemConstant.DEFAULT_PASSWORD, dbUser.getSalt()));
        int i = userMapper.updateById(dbUser);
        if (i != 1) {
            throw new CustomerException(UserCode.PASSWORD_RESET_FAILURE);
        }
    }

    /**
     * 用户修改自己的密码
     *
     * @param userPasswordDto 操作需要的实体信息
     */
    @Override
    public void editPassword(UserPasswordDto userPasswordDto) {
        if (ObjectUtil.isNull(userPasswordDto.getId())) {
            throw new CustomerException(ResultCode.HANDLE_DATA_NOT_EXISTED, "修改用户密码时，没有用户的id");
        }
        if (StrUtil.isBlank(userPasswordDto.getOldPassword())) {
            throw new CustomerException(ResultCode.HANDLE_DATA_NOT_EXISTED, "修改用户密码时，原密码不能为空");
        }
        if (StrUtil.isBlank(userPasswordDto.getNewPassword())) {
            throw new CustomerException(ResultCode.HANDLE_DATA_NOT_EXISTED, "修改用户密码时，新密码不能为空");
        }
        User dbUser = userMapper.selectById(userPasswordDto.getId());
        if (ObjectUtil.isNull(dbUser)) {
            throw new CustomerException(ResultCode.HANDLE_DATA_NOT_EXISTED, "修改用户密码时，没有用户的信息");
        }
        String encrypt = EncryptUtils.encrypt(userPasswordDto.getOldPassword(), dbUser.getSalt());
        if (!encrypt.equals(dbUser.getPassword())) {
            throw new CustomerException(UserCode.INCORRECT_OLD_PASSWORD);
        }
        dbUser.setPassword(EncryptUtils.encrypt(userPasswordDto.getNewPassword(), dbUser.getSalt()));
        int i = userMapper.updateById(dbUser);
        if (i != 1) {
            throw new CustomerException(UserCode.PASSWORD_EDIT_FAILURE);
        }
    }

    /**
     * 当用户密码为初始密码时，强制修改用户密码
     *
     * @param userPasswordDto 操作需要的实体信息
     */
    @Override
    public void forceEditPassword(UserPasswordDto userPasswordDto) {
        if (ObjectUtil.isNull(userPasswordDto.getId())) {
            throw new CustomerException(ResultCode.HANDLE_DATA_NOT_EXISTED, "修改用户密码时，没有该用户的id");
        }
        if (StrUtil.isBlank(userPasswordDto.getNewPassword())) {
            throw new CustomerException(ResultCode.HANDLE_DATA_NOT_EXISTED, "修改用户密码时，新密码不能为空");
        }
        User dbUser = userMapper.selectById(userPasswordDto.getId());
        if (ObjectUtil.isNull(dbUser)) {
            throw new CustomerException(ResultCode.HANDLE_DATA_NOT_EXISTED, "修改用户密码时，没有该用户的信息");
        }
        dbUser.setPassword(EncryptUtils.encrypt(userPasswordDto.getNewPassword(), dbUser.getSalt()));
        int i = userMapper.updateById(dbUser);
        if (i != 1) {
            throw new CustomerException(UserCode.PASSWORD_FORCE_EDIT_FAILURE);
        }
    }

}
